import 'package:flutter/material.dart';

class DraggablePage extends StatefulWidget {
  final Map<String, dynamic> arguments;
  DraggablePage({Key key, this.arguments}) : super(key: key);

  @override
  _DraggablePageState createState() => _DraggablePageState();
}

class _DraggablePageState extends State<DraggablePage> {
  BlockModel _model;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('DraggablePage'),
      ),
      body: ListView(
        children: <Widget>[
          ListTile(
            title: Text('Draggable & DragTarget'),
            subtitle: Column(
              children: <Widget>[
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                  children: <Widget>[
                    DragBlock(model: BlockModel(title: 'Apple', color: Colors.red)),
                    DragBlock(model: BlockModel(title: 'Banana', color: Colors.cyan)),
                  ],
                ),
                SizedBox(height: 20.0),
                Container(
                  height: 200.0,
                  child: DragTarget<BlockModel>(
                    // Draggable 经过<手指中心位置, 非控件中心位置>时调用, 返回 true 时, 手指松开后回调 onAccept.
                    onWillAccept: (value) {
                      print('onWillAccept: ${value.title}');
                      return true;
                    },
                    // 松手时调用(onWillAccept 需要返回 true)
                    onAccept: (value) {
                      print('onAccept: ${value.title}');
                      _model = value;
                    },
                    // 离开 DragTarget 时(手放开情况离开不回调)
                    onLeave: (value) {
                      print(value);
                    },
                    // 构造部件 (onWillAccept 返回为 true 时, candidateData[0] 为 Draggable 的 data, 否则 rejectedData[0] 为 Draggable 的 data.)
                    // 一般用于拖动过程中(手未放开)时的值获取.
                    builder: (BuildContext context, candidateData, rejectedData) {
                      print('builder');
                      bool haveModel = _model != null;
                      return Container(
                        color: haveModel ? _model.color : Colors.grey.withAlpha(255 ~/ 2.0),
                        child: Center(
                          child: Text(
                            haveModel ? _model.title : '请拖动到此区域',
                            style: TextStyle(
                              fontSize: 30.0,
                              color: haveModel ? Colors.black : Colors.grey,
                            ),
                          ),
                        ),
                      );
                    },
                  ),
                )
              ],
            ),
          ),
          Divider(height: 1.0),
        ],
      ),
    );
  }
}

/// 用于拖动的方块
class DragBlock extends StatefulWidget {
  final BlockModel model;
  DragBlock({Key key, @required this.model}) : super(key: key);

  @override
  _DragBlockState createState() => _DragBlockState();
}

class _DragBlockState extends State<DragBlock> {
  @override
  Widget build(BuildContext context) {
    return Draggable<BlockModel>(
      // 可以指定拖动方向
      // axis: Axis.vertical,
      // 自持有数据, 与 DragTarget 配合使用, 将用于传递给 DragTarget 部件.
      data: widget.model,
      // 静止部件
      child: Container(
        width: 100.0,
        height: 100.0,
        color: widget.model.color,
        child: Center(
          child: Text(widget.model.title),
        ),
      ),
      // 拖动后替换原位置显示的部件(可以不传)
      childWhenDragging: Container(
        color: Colors.grey.withAlpha(255 ~/ 2.0),
        width: 100.0,
        height: 100.0,
      ),
      // 拖动中的部件(添加 Material 以防止拖动后文字底部双下划线)
      feedback: Material(
        child: Container(
          width: 110.0,
          height: 110.0,
          color: widget.model.color,
          child: Center(
            child: Text(widget.model.title, style: TextStyle(color: Colors.black, fontSize: 14.0)),
          ),
        ),
      ),
      // 拖动开始
      onDragStarted: () {
        print('onDragStarted');
      },
      // 未拖动到 DragTarget
      onDraggableCanceled: (Velocity velocity, Offset offset) {
        print('onDraggableCanceled');
      },
      // 拖动到 DragTarget
      onDragCompleted: () {
        print('onDragCompleted');
      },
      // 拖动结束
      onDragEnd: (DraggableDetails details) {
        print('onDragEnd');
      },
    );
  }
}

/// 方块模型
class BlockModel {
  final String title;
  final Color color;

  const BlockModel({@required this.title, @required this.color});
}
